library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity cy7c68013a_if_module is
	port (
		avs_s0_address     : in  std_logic_vector(7 downto 0)  := (others => '0'); --    s0.address
		avs_s0_read        : in  std_logic                     := '0';             --      .read
		avs_s0_readdata    : out std_logic_vector(31 downto 0);                    --      .readdata
		avs_s0_write       : in  std_logic                     := '0';             --      .write
		avs_s0_writedata   : in  std_logic_vector(31 downto 0) := (others => '0'); --      .writedata
		avs_s0_waitrequest : out std_logic;                                        --      .waitrequest
		clk                : in  std_logic                     := '0';             -- clock.clk
		reset              : in  std_logic                     := '0';             -- reset.reset
		ins_irq0_irq       : out std_logic;                                        --  irq0.irq
		cha_fifo_data	   : in std_logic_vector(15 downto 0);
		cha_fifo_rdempty   : in std_logic;
		cha_fifo_rdreq     : out std_logic;
		chb_fifo_data	   : in std_logic_vector(15 downto 0);
		chb_fifo_rdempty   : in std_logic;
		chb_fifo_rdreq     : out std_logic;
		la_fifo_data	   : in std_logic_vector(15 downto 0);
		la_fifo_rdempty    : in std_logic;
		la_fifo_rdreq	   : out std_logic;
		flaga_raw		   : in std_logic; --EP8 empty,active low
		flagb_raw		   : in std_logic; --EP2 full,active low
		flagc_raw		   : in std_logic;
		slwr			   : out std_logic;
		slrd			   : out std_logic;
		sloe			   : out std_logic;
		pktend			   : out std_logic;
		fifoadr			   : out std_logic_vector(1 downto 0);
		fd				   : inout std_logic_vector(15 downto 0);
		soc_ready		   : out std_logic
	);
end cy7c68013a_if_module;
architecture rtl of cy7c68013a_if_module is
component if_tx is
	port(
		data_tx: out std_logic_vector(15 downto 0);
		cha_fifo_data: in std_logic_vector(15 downto 0);
		chb_fifo_data: in std_logic_vector(15 downto 0);
		la_fifo_data: in std_logic_vector(15 downto 0);
		cha_fifo_rdreq: out std_logic;
		chb_fifo_rdreq: out std_logic;
		la_fifo_rdreq: out std_logic;
		cha_fifo_rdempty: in std_logic;
		chb_fifo_rdempty: in std_logic;
		la_fifo_rdempty: in std_logic;
		fifo_sel: in std_logic_vector(2 downto 0);
		flagb: in std_logic; --EP2 full,active low
		slwr: out std_logic;
		pktend: out std_logic;
		ifclk: in std_logic;
		rst: in std_logic;
		packet_header: in std_logic_vector(31 downto 0);
		start_tx: in std_logic
	);
end component;
component if_rx is
	port(
		data_rx: in std_logic_vector(15 downto 0);
		start_rx: in std_logic;
		received_packet: out std_logic_vector(31 downto 0);
		slrd: out std_logic;
		sloe: out std_logic;
		rx_busy: out std_logic;
		ifclk: in std_logic;
		rst: in std_logic
	);
end component;
signal ep8_not_empty_irq: std_logic;
signal ep8_not_empty_irq_en: std_logic;
signal cha_fifo_rdempty_irq,cha_fifo_rdempty_irq_en:std_logic;
signal chb_fifo_rdempty_irq,chb_fifo_rdempty_irq_en:std_logic;
signal la_fifo_rdempty_irq,la_fifo_rdempty_irq_en:std_logic;
signal data_bus_dir:std_logic;
signal fifo_sel:std_logic_vector(2 downto 0);
signal data_tx,data_rx:std_logic_vector(15 downto 0);
signal start_rx:std_logic;
signal start_tx:std_logic;
signal packet_header:std_logic_vector(31 downto 0);
signal received_packet: std_logic_vector(31 downto 0);
signal ep8_not_empty: std_logic;
signal rx_busy: std_logic;
signal flaga,flagb,flagc:std_logic;
begin
	U1: if_tx port map(
		data_tx => data_tx,
		cha_fifo_data => cha_fifo_data,
		chb_fifo_data => chb_fifo_data,
		la_fifo_data => la_fifo_data,
		cha_fifo_rdreq => cha_fifo_rdreq,
		chb_fifo_rdreq => chb_fifo_rdreq,
		la_fifo_rdreq => la_fifo_rdreq,
		cha_fifo_rdempty => cha_fifo_rdempty,
		chb_fifo_rdempty => chb_fifo_rdempty,
		la_fifo_rdempty => la_fifo_rdempty,
		fifo_sel => fifo_sel,
		flagb => flagb,		--EP2 full,active low
		slwr => slwr,
		pktend => pktend,
		ifclk => clk,
		rst => reset,
		packet_header => packet_header,
		start_tx => start_tx
	);
	U2: if_rx port map(
		data_rx => data_rx,
		start_rx => start_rx,
		received_packet => received_packet,
		slrd => slrd,
		sloe => sloe,
		rx_busy => rx_busy,
		ifclk => clk,
		rst => reset
	);
	avs_s0_waitrequest <= '0';
	data_rx <= fd;
	fd <= (others => 'Z') when data_bus_dir = '0' else data_tx;
	ep8_not_empty <= flaga;
   	la_fifo_rdempty_irq <= la_fifo_rdempty when la_fifo_rdempty_irq_en = '1' else '0';
	chb_fifo_rdempty_irq <= chb_fifo_rdempty when chb_fifo_rdempty_irq_en = '1' else '0';
	cha_fifo_rdempty_irq <= cha_fifo_rdempty when cha_fifo_rdempty_irq_en = '1' else '0';
	ep8_not_empty_irq <= ep8_not_empty when ep8_not_empty_irq_en = '1' else '0';
    ins_irq0_irq <= ep8_not_empty_irq or cha_fifo_rdempty_irq or chb_fifo_rdempty_irq or la_fifo_rdempty_irq;
	
    process(clk)
	begin
		if(clk = '1' and clk'event) then
			flaga <= flaga_raw;
			flagb <= flagb_raw;
			flagc <= flagc_raw;
			if(data_bus_dir = '0') then
				fifoadr <= "11";
			else
				fifoadr <= "00";
			end if;
		end if;
	end process;
	process(clk,reset)
	begin
		if(reset = '1') then
			avs_s0_readdata <= (others => '0');
			ep8_not_empty_irq_en <= '0';
			cha_fifo_rdempty_irq_en <= '0';
			chb_fifo_rdempty_irq_en <= '0';
			la_fifo_rdempty_irq_en <= '0';
			fifo_sel <= (others => '0');
			data_bus_dir <= '0';
			start_tx <= '0';
			start_rx <= '0';
			packet_header <= (others => '0');
			soc_ready <= '1';
		elsif(clk = '1' and clk'event) then
			if(avs_s0_read = '1') then
				case avs_s0_address is
					when x"00" =>
						avs_s0_readdata(31 downto 4) <= (others => '0');
						avs_s0_readdata(3) <= la_fifo_rdempty_irq;
						avs_s0_readdata(2) <= chb_fifo_rdempty_irq;
						avs_s0_readdata(1) <= cha_fifo_rdempty_irq;
						avs_s0_readdata(0) <= ep8_not_empty_irq;
					when x"01" =>
						avs_s0_readdata(31 downto 4) <= (others => '0');
						avs_s0_readdata(3) <= la_fifo_rdempty_irq_en;
						avs_s0_readdata(2) <= chb_fifo_rdempty_irq_en;
						avs_s0_readdata(1) <= cha_fifo_rdempty_irq_en;
						avs_s0_readdata(0) <= ep8_not_empty_irq_en;
					when x"03" =>
						avs_s0_readdata(31 downto 3) <= (others => '0');
						avs_s0_readdata(2) <= flagc;
						avs_s0_readdata(1) <= flagb;
						avs_s0_readdata(0) <= flaga;
					when x"07" =>
						avs_s0_readdata <= received_packet;
					when x"09" =>
						avs_s0_readdata(31 downto 4) <= (others =>'0');
						avs_s0_readdata(3) <= la_fifo_rdempty;
						avs_s0_readdata(2) <= chb_fifo_rdempty;
						avs_s0_readdata(1) <= cha_fifo_rdempty;
						avs_s0_readdata(0) <= ep8_not_empty;
					when x"0a" =>
                        avs_s0_readdata(31 downto 1) <= (others =>'0');
						avs_s0_readdata(0) <= rx_busy;
					when others =>
						null;
				end case;
			elsif(avs_s0_write = '1') then
				case avs_s0_address is
					when x"01" =>
                        la_fifo_rdempty_irq_en <= avs_s0_writedata(3);
						chb_fifo_rdempty_irq_en <= avs_s0_writedata(2);
						cha_fifo_rdempty_irq_en <= avs_s0_writedata(1);
						ep8_not_empty_irq_en <= avs_s0_writedata(0);
					when x"02" =>
						data_bus_dir <= avs_s0_writedata(0);
					when x"04" =>
						fifo_sel <= avs_s0_writedata(2 downto 0);
					when x"05" =>
						start_tx <= avs_s0_writedata(0);
					when x"06" =>
						packet_header <= avs_s0_writedata(31 downto 0);
					when x"08" =>
						start_rx <= avs_s0_writedata(0);
					when x"0c" =>
						soc_ready <= avs_s0_writedata(0);
					when others =>
						null;
				end case;
			end if;
			if(start_tx = '1') then 
				start_tx <= '0';
			end if;
			if(start_rx = '1') then
				start_rx <= '0';
			end if;
		end if; 
	end process;
end rtl;